using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using Northwoods.Go;

namespace Workflows.Diagrams
{
    [Serializable()]
    public class SubGraphDraggingTool : GoToolDragging
    {
        #region members
        private bool myOriginalDragsRealtime = false;
        private GoSubGraph myTargetSubGraph = null;
        private Color myTargetColor = Color.Empty;
        #endregion

        #region ctor
        public SubGraphDraggingTool(GoView view)
            : base(view)
        {
        }
        #endregion

        #region overrides
        public override void Start()
        {
            this.myOriginalDragsRealtime = this.View.DragsRealtime;
            base.Start();
        }

        public override void Stop()
        {
            this.View.DragsRealtime = this.myOriginalDragsRealtime;
            this.UnhighlightSubGraph();
            base.Stop();
        }

        public override void DoDragging(GoInputState evttype)
        {
            if (this.CurrentObject == null)
                return;
            if (this.MustBeMoving() && (this.Selection.Primary != null))
            {
                this.View.DragsRealtime = false;
                GoSubGraph sg = this.FindSubGraph(this.LastInput.DocPoint, this.Selection.Primary);
                if (sg != null)
                {
                    if (evttype == GoInputState.Continue)
                    {
                        if ((!this.myTargetSubGraph.Equals(sg)) && (!this.Selection.Primary.Equals(sg)))
                        {
                            this.UnhighlightSubGraph();
                            this.myTargetSubGraph = sg;
                            this.HighlightSubGraph(Color.Red);
                        }
                    }
                    else if (evttype == GoInputState.Finish)
                    {
                        bool expandFirst = !sg.IsExpanded;
                        if (expandFirst)
                            sg.Expand();
                        base.DoDragging(evttype);
                        sg.AddCollection(this.EffectiveSelection, true);
                        if (expandFirst)
                            sg.Collapse();
                        return;
                    }
                }
                else
                {
                    this.UnhighlightSubGraph();
                    base.DoDragging(evttype);
                    if (evttype == GoInputState.Finish)
                    {
                        this.View.Document.Layers.Default.AddCollection(this.Selection, true);
                    }
                    return;
                }
            }
            else
            {
                this.View.DragsRealtime = this.myOriginalDragsRealtime;
                this.UnhighlightSubGraph();
            }
            base.DoDragging(evttype);
        }
        #endregion

        public virtual GoSubGraph FindSubGraph(PointF pt, GoObject skip)
        {
            foreach (GoObject obj in this.View.Document.Backwards)
            {
                GoSubGraph sg = this.FindSubGraph(obj, pt, skip);
                if (sg != null)
                {
                    return sg;
                }
            }
            return null;
        }


        public GoSubGraph FindSubGraph(GoObject obj, PointF pt, GoObject skip)
        {
            if (!obj.CanView())
            {
                return null;
            }

            if (obj.Equals(skip) || skip.IsChildOf(obj))
            {
                return null;
            }

            GoSubGraph sg = null;
            if (obj.GetType() == typeof(GoSubGraph))
                sg = (GoSubGraph)obj;
            if (sg != null)
            {
                RectangleF rect = obj.Bounds;
                if (rect.Contains(pt))
                {
                    foreach (GoObject o in sg)
                    {
                        GoSubGraph subGraph = this.FindSubGraph(o, pt, skip);
                        if (subGraph != null)
                        {
                            return subGraph;
                        }
                    }
                    return sg;
                }
            }
            return null;
        }

        #region private methods
        private void UnhighlightSubGraph()
        {
            if (this.myTargetSubGraph != null)
            {
                this.myTargetSubGraph.SkipsUndoManager = true;
                this.myTargetSubGraph.BackgroundColor = this.myTargetColor;
                this.myTargetSubGraph.SkipsUndoManager = false;
                this.myTargetSubGraph = null;
            }
        }

        private void HighlightSubGraph(Color c)
        {
            if (this.myTargetSubGraph != null)
            {
                this.myTargetColor = myTargetSubGraph.BackgroundColor;
                this.myTargetSubGraph.SkipsUndoManager = true;
                this.myTargetSubGraph.BackgroundColor = c;
                this.myTargetSubGraph.SkipsUndoManager = false;
            }
        }
        #endregion
    }
}
